home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / pax / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-02-02  |  55.6 KB

  1. Subject:  v17i076:  Usenix/IEEE POSIX replacement for TAR and CPIO, Part03/06
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Mark H. Colburn <mark@jhereg.jhereg.mn.org>
  6. Posting-number: Volume 17, Issue 76
  7. Archive-name: pax/part03
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 3 (of 6)."
  16. # Contents:  fileio.c namelist.c pax.c pax.h tar.c
  17. # Wrapped by mark@jhereg on Tue Dec 27 19:37:45 1988
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f fileio.c -a "${1}" != "-c" ; then 
  20.   echo shar: Will not over-write existing file \"fileio.c\"
  21. else
  22. echo shar: Extracting \"fileio.c\" \(10596 characters\)
  23. sed "s/^X//" >fileio.c <<'END_OF_fileio.c'
  24. X/* $Source: /u/mark/src/pax/RCS/fileio.c,v $
  25. X *
  26. X * $Revision: 1.1 $
  27. X *
  28. X * fileio.c - file I/O functions for all archive interfaces
  29. X *
  30. X * DESCRIPTION
  31. X *
  32. X *    These function all do I/O of some form or another.  They are
  33. X *    grouped here mainly for convienence.
  34. X *
  35. X * AUTHOR
  36. X *
  37. X *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  38. X *
  39. X * Sponsored by The USENIX Association for public distribution. 
  40. X *
  41. X * Copyright (c) 1989 Mark H. Colburn.
  42. X * All rights reserved.
  43. X *
  44. X * Redistribution and use in source and binary forms are permitted
  45. X * provided that the above copyright notice is duplicated in all such 
  46. X * forms and that any documentation, advertising materials, and other 
  47. X * materials related to such distribution and use acknowledge that the 
  48. X * software was developed * by Mark H. Colburn and sponsored by The 
  49. X * USENIX Association. 
  50. X *
  51. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  52. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  53. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  54. X *
  55. X * $Log:    fileio.c,v $
  56. X * Revision 1.1  88/12/23  18:02:09  mark
  57. X * Initial revision
  58. X * 
  59. X */
  60. X
  61. X#ifndef lint
  62. Xstatic char *ident = "$Id: fileio.c,v 1.1 88/12/23 18:02:09 mark Rel $";
  63. Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  64. X#endif /* ! lint */
  65. X
  66. X
  67. X/* Headers */
  68. X
  69. X#include "pax.h"
  70. X
  71. X
  72. X/* open_archive -  open an archive file.  
  73. X *
  74. X * DESCRIPTION
  75. X *
  76. X *    Open_archive will open an archive file for reading or writing,
  77. X *    setting the proper file mode, depending on the "mode" passed to
  78. X *    it.  All buffer pointers are reset according to the mode
  79. X *    specified.
  80. X *
  81. X * PARAMETERS
  82. X *
  83. X *     int    mode     - specifies whether we are reading or writing.   
  84. X *
  85. X * RETURNS
  86. X *
  87. X *    Returns a zero if successfull, or -1 if an error occured during 
  88. X *    the open.
  89. X */
  90. X
  91. X#ifdef __STDC__
  92. X    
  93. Xint open_archive(int mode)
  94. X
  95. X#else
  96. X    
  97. Xint open_archive(mode)
  98. Xint             mode;
  99. X
  100. X#endif
  101. X{
  102. X    if (ar_file[0] == '-' && ar_file[1] == '\0') {
  103. X    if (mode == AR_READ) {
  104. X        archivefd = STDIN;
  105. X        bufend = bufidx = bufstart;
  106. X    } else {
  107. X        archivefd = STDOUT;
  108. X    }
  109. X    } else if (mode == AR_READ) {
  110. X    archivefd = open(ar_file, O_RDONLY | O_BINARY);
  111. X    bufend = bufidx = bufstart;    /* set up for initial read */
  112. X    } else if (mode == AR_WRITE) {
  113. X    archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
  114. X    } else if (mode == AR_APPEND) {
  115. X    archivefd = open(ar_file, O_RDWR | O_BINARY, 0666);
  116. X    bufend = bufidx = bufstart;    /* set up for initial read */
  117. X    }
  118. X
  119. X    if (archivefd < 0) {
  120. X    warnarch(syserr(), (OFFSET) 0);
  121. X    return (-1);
  122. X    }
  123. X    ++arvolume;
  124. X    return (0);
  125. X}
  126. X
  127. X
  128. X/* close_archive - close the archive file
  129. X *
  130. X * DESCRIPTION
  131. X *
  132. X *    Closes the current archive and resets the archive end of file
  133. X *    marker.
  134. X */
  135. X
  136. X#ifdef __STDC__
  137. X
  138. Xvoid close_archive(void)
  139. X
  140. X#else
  141. X    
  142. Xvoid close_archive()
  143. X
  144. X#endif
  145. X{
  146. X    if (archivefd != STDIN && archivefd != STDOUT) {
  147. X    close(archivefd);
  148. X    }
  149. X    areof = 0;
  150. X}
  151. X
  152. X
  153. X/* openo - open an output file
  154. X *
  155. X * DESCRIPTION
  156. X *
  157. X *    Openo opens the named file for output.  The file mode and type are
  158. X *    set based on the values stored in the stat structure for the file.
  159. X *    If the file is a special file, then no data will be written, the
  160. X *    file/directory/Fifo, etc., will just be created.  Appropriate
  161. X *    permission may be required to create special files.
  162. X *
  163. X * PARAMETERS
  164. X *
  165. X *    char     *name        - The name of the file to create
  166. X *    Stat    *asb        - Stat structure for the file
  167. X *    Link    *linkp;        - pointer to link chain for this file
  168. X *    int     ispass        - true if we are operating in "pass" mode
  169. X *
  170. X * RETURNS
  171. X *
  172. X *     Returns the output file descriptor, 0 if no data is required or -1 
  173. X *    if unsuccessful. Note that UNIX open() will never return 0 because 
  174. X *    the standard input is in use. 
  175. X */
  176. X
  177. X#ifdef __STDC__
  178. X
  179. Xint openo(char *name, Stat *asb, Link *linkp, int ispass)
  180. X
  181. X#else
  182. X    
  183. Xint openo(name, asb, linkp, ispass)
  184. Xchar           *name;
  185. XStat           *asb;
  186. XLink           *linkp;
  187. Xint             ispass;
  188. X
  189. X#endif
  190. X{
  191. X    int             exists;
  192. X    int             fd;
  193. X    ushort          perm;
  194. X    ushort          operm = 0;
  195. X    Stat            osb;
  196. X#ifdef    S_IFLNK
  197. X    int             ssize;
  198. X    char            sname[PATH_MAX + 1];
  199. X#endif    /* S_IFLNK */
  200. X
  201. X    if (exists = (LSTAT(name, &osb) == 0)) {
  202. X    if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
  203. X        warn(name, "Same file");
  204. X        return (-1);
  205. X    } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
  206. X        operm = osb.sb_mode & S_IPERM;
  207. X    } else if (REMOVE(name, &osb) < 0) {
  208. X        warn(name, syserr());
  209. X        return (-1);
  210. X    } else {
  211. X        exists = 0;
  212. X    }
  213. X    }
  214. X    if (linkp) {
  215. X    if (exists) {
  216. X        if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
  217. X        return (0);
  218. X        } else if (unlink(name) < 0) {
  219. X        warn(name, syserr());
  220. X        return (-1);
  221. X        } else {
  222. X        exists = 0;
  223. X        }
  224. X    }
  225. X    if (link(linkp->l_name, name) != 0) {
  226. X        if (errno == ENOENT) {
  227. X        if (f_create_dirs) {
  228. X            if (dirneed(name) != 0 ||
  229. X                link(linkp->l_name, name) != 0) {
  230. X                warn(name, syserr());
  231. X            return (-1);
  232. X            }
  233. X        } else {
  234. X            warn(name, 
  235. X                 "Directories are not being created (-d option)");
  236. X        }
  237. X        return(0);
  238. X        } else if (errno != EXDEV) {
  239. X        warn(name, syserr());
  240. X        return (-1);
  241. X        }
  242. X    } else {
  243. X        return(0);
  244. X    } 
  245. X    }
  246. X    perm = asb->sb_mode & S_IPERM;
  247. X    switch (asb->sb_mode & S_IFMT) {
  248. X    case S_IFBLK:
  249. X    case S_IFCHR:
  250. X    fd = 0;
  251. X    if (exists) {
  252. X        if (asb->sb_rdev == osb.sb_rdev) {
  253. X        if (perm != operm && chmod(name, (int) perm) < 0) {
  254. X            warn(name, syserr());
  255. X            return (-1);
  256. X        } else {
  257. X            break;
  258. X        }
  259. X        } else if (REMOVE(name, &osb) < 0) {
  260. X        warn(name, syserr());
  261. X        return (-1);
  262. X        } else {
  263. X        exists = 0;
  264. X        }
  265. X    }
  266. X    if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
  267. X        if (errno == ENOENT) {
  268. X        if (f_create_dirs) {
  269. X            if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode, 
  270. X               (int) asb->sb_rdev) < 0) {
  271. X            warn(name, syserr());
  272. X            return (-1);
  273. X            }
  274. X        } else {
  275. X            warn(name, "Directories are not being created (-d option)");
  276. X        }
  277. X        } else {
  278. X        warn(name, syserr());
  279. X        return (-1);
  280. X        }
  281. X    }
  282. X    return(0);
  283. X    break;
  284. X    case S_IFDIR:
  285. X    if (exists) {
  286. X        if (perm != operm && chmod(name, (int) perm) < 0) {
  287. X        warn(name, syserr());
  288. X        return (-1);
  289. X        }
  290. X    } else if (f_create_dirs) {
  291. X        if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
  292. X        warn(name, syserr());
  293. X        return (-1);
  294. X        }
  295. X    } else {
  296. X        warn(name, "Directories are not being created (-d option)");
  297. X    }
  298. X    return (0);
  299. X#ifdef    S_IFIFO
  300. X    case S_IFIFO:
  301. X    fd = 0;
  302. X    if (exists) {
  303. X        if (perm != operm && chmod(name, (int) perm) < 0) {
  304. X        warn(name, syserr());
  305. X        return (-1);
  306. X        }
  307. X    } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
  308. X        if (errno == ENOENT) {
  309. X        if (f_create_dirs) {
  310. X            if (dirneed(name) < 0
  311. X               || mknod(name, (int) asb->sb_mode, 0) < 0) {
  312. X            warn(name, syserr());
  313. X            return (-1);
  314. X            }
  315. X        } else {
  316. X            warn(name, "Directories are not being created (-d option)");
  317. X        }
  318. X        } else {
  319. X        warn(name, syserr());
  320. X        return (-1);
  321. X        }
  322. X    }
  323. X    return(0);
  324. X    break;
  325. X#endif                /* S_IFIFO */
  326. X#ifdef    S_IFLNK
  327. X    case S_IFLNK:
  328. X    if (exists) {
  329. X        if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
  330. X        warn(name, syserr());
  331. X        return (-1);
  332. X        } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
  333. X        return (0);
  334. X        } else if (REMOVE(name, &osb) < 0) {
  335. X        warn(name, syserr());
  336. X        return (-1);
  337. X        } else {
  338. X        exists = 0;
  339. X        }
  340. X    }
  341. X    if (symlink(asb->sb_link, name) < 0) {
  342. X        if (errno == ENOENT) {
  343. X        if (f_create_dirs) {
  344. X            if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
  345. X            warn(name, syserr());
  346. X            return (-1);
  347. X            }
  348. X        } else {
  349. X            warn(name, "Directories are not being created (-d option)");
  350. X        }
  351. X        } else {
  352. X        warn(name, syserr());
  353. X        return (-1);
  354. X        }
  355. X    }
  356. X    return (0);        /* Can't chown()/chmod() a symbolic link */
  357. X#endif                /* S_IFLNK */
  358. X    case S_IFREG:
  359. X    if (exists) {
  360. X        if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
  361. X        warn(name, "Newer file exists");
  362. X        return (-1);
  363. X        } else if (unlink(name) < 0) {
  364. X        warn(name, syserr());
  365. X        return (-1);
  366. X        } else {
  367. X        exists = 0;
  368. X        }
  369. X    }
  370. X    if ((fd = creat(name, (int) perm)) < 0) {
  371. X        if (errno == ENOENT) {
  372. X        if (f_create_dirs) {
  373. X            if (dirneed(name) < 0 || 
  374. X                (fd = creat(name, (int) perm)) < 0) {
  375. X            warn(name, syserr());
  376. X            return (-1);
  377. X            }
  378. X        } else {
  379. X            /* 
  380. X             * the file requires a directory which does not exist
  381. X             * and which the user does not want created, so skip
  382. X             * the file...
  383. X             */
  384. X            warn(name, "Directories are not being created (-d option)");
  385. X            return(0);
  386. X        }
  387. X        } else {
  388. X        warn(name, syserr());
  389. X        return (-1);
  390. X        }
  391. X    }
  392. X    break;
  393. X    default:
  394. X    warn(name, "Unknown filetype");
  395. X    return (-1);
  396. X    }
  397. X    if (f_owner) {
  398. X    if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
  399. X        chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
  400. X    }
  401. X    }
  402. X    return (fd);
  403. X}
  404. X
  405. X
  406. X/* openi - open the next input file
  407. X *
  408. X * DESCRIPTION
  409. X *
  410. X *    Openi will attempt to open the next file for input.  If the file is
  411. X *    a special file, such as a directory, FIFO, link, character- or
  412. X *    block-special file, then the file size field of the stat structure
  413. X *    is zeroed to make sure that no data is written out for the file.
  414. X *    If the file is a special file, then a file descriptor of 0 is
  415. X *    returned to the caller, which is handled specially.  If the file
  416. X *    is a regular file, then the file is opened and a file descriptor
  417. X *    to the open file is returned to the caller.
  418. X *
  419. X * PARAMETERS
  420. X *
  421. X *    char   *name    - pointer to the name of the file to open
  422. X *    Stat   *asb    - pointer to the stat block for the file to open
  423. X *
  424. X * RETURNS
  425. X *
  426. X *     Returns a file descriptor, 0 if no data exists, or -1 at EOF. This 
  427. X *    kludge works because standard input is in use, preventing open() from 
  428. X *    returning zero. 
  429. X */
  430. X
  431. X#ifdef __STDC__
  432. X
  433. Xint openi(char *name, Stat *asb)
  434. X
  435. X#else
  436. X    
  437. Xint openi(name, asb)
  438. Xchar           *name;        /* name of file to open */
  439. XStat           *asb;        /* pointer to stat structure for file */
  440. X
  441. X#endif
  442. X{
  443. X    int             fd;
  444. X
  445. X    switch (asb->sb_mode & S_IFMT) {
  446. X    case S_IFDIR:
  447. X    asb->sb_nlink = 1;
  448. X    asb->sb_size = 0;
  449. X    return (0);
  450. X#ifdef    S_IFLNK
  451. X    case S_IFLNK:
  452. X    if ((asb->sb_size = readlink(name,
  453. X                 asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
  454. X        warn(name, syserr());
  455. X        return(0);
  456. X    }
  457. X    asb->sb_link[asb->sb_size] = '\0';
  458. X    return (0);
  459. X#endif                /* S_IFLNK */
  460. X    case S_IFREG:
  461. X    if (asb->sb_size == 0) {
  462. X        return (0);
  463. X    }
  464. X    if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
  465. X        warn(name, syserr());
  466. X    }
  467. X    return (fd);
  468. X    default:
  469. X    asb->sb_size = 0;
  470. X    return (0);
  471. X    }
  472. X}
  473. END_OF_fileio.c
  474. if test 10596 -ne `wc -c <fileio.c`; then
  475.     echo shar: \"fileio.c\" unpacked with wrong size!
  476. fi
  477. # end of overwriting check
  478. fi
  479. if test -f namelist.c -a "${1}" != "-c" ; then 
  480.   echo shar: Will not over-write existing file \"namelist.c\"
  481. else
  482. echo shar: Extracting \"namelist.c\" \(11056 characters\)
  483. sed "s/^X//" >namelist.c <<'END_OF_namelist.c'
  484. X/* $Source: /u/mark/src/pax/RCS/namelist.c,v $
  485. X *
  486. X * $Revision: 1.1 $
  487. X *
  488. X * namelist.c - track filenames given as arguments to tar/cpio/pax
  489. X *
  490. X * DESCRIPTION
  491. X *
  492. X *    Arguments may be regular expressions, therefore all agurments will
  493. X *    be treated as if they were regular expressions, even if they are
  494. X *    not.
  495. X *
  496. X * AUTHOR
  497. X *
  498. X *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  499. X *
  500. X * Sponsored by The USENIX Association for public distribution. 
  501. X *
  502. X * Copyright (c) 1989 Mark H. Colburn.
  503. X * All rights reserved.
  504. X *
  505. X * Redistribution and use in source and binary forms are permitted
  506. X * provided that the above copyright notice is duplicated in all such 
  507. X * forms and that any documentation, advertising materials, and other 
  508. X * materials related to such distribution and use acknowledge that the 
  509. X * software was developed * by Mark H. Colburn and sponsored by The 
  510. X * USENIX Association. 
  511. X *
  512. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  513. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  514. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  515. X *
  516. X * $Log:    namelist.c,v $
  517. X * Revision 1.1  88/12/23  18:02:17  mark
  518. X * Initial revision
  519. X * 
  520. X */
  521. X
  522. X#ifndef lint
  523. Xstatic char *ident = "$Id: namelist.c,v 1.1 88/12/23 18:02:17 mark Rel $";
  524. Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  525. X#endif /* ! lint */
  526. X
  527. X
  528. X/* Headers */
  529. X
  530. X#include "pax.h"
  531. X
  532. X
  533. X/* Type Definitions */
  534. X
  535. X/*
  536. X * Structure for keeping track of filenames and lists thereof. 
  537. X */
  538. Xstruct nm_list {
  539. X    struct nm_list *next;
  540. X    short           length;    /* cached strlen(name) */
  541. X    char            found;    /* A matching file has been found */
  542. X    char            firstch;    /* First char is literally matched */
  543. X    char            regexp;    /* regexp pattern for item */
  544. X    char            name[1];    /* name of file or rexexp */
  545. X};
  546. X
  547. Xstruct dirinfo {
  548. X    char            dirname[PATH_MAX + 1];    /* name of directory */
  549. X    OFFSET        where;    /* current location in directory */
  550. X    struct dirinfo *next;
  551. X};
  552. X
  553. X
  554. X/* Function Prototypes */
  555. X
  556. X#ifndef __STDC__
  557. X
  558. Xstatic void pushdir();
  559. Xstatic struct dirinfo *popdir();
  560. X
  561. X#else
  562. X
  563. Xstatic void pushdir(struct dirinfo *info);
  564. Xstatic struct dirinfo *popdir(void);
  565. X
  566. X#endif
  567. X
  568. X
  569. X/* Internal Identifiers */
  570. X
  571. Xstatic struct nm_list *namelast;    /* Points to last name in list */
  572. Xstatic struct nm_list *namelist;    /* Points to first name in list */
  573. X
  574. X
  575. X/* addname -  add a name to the namelist. 
  576. X *
  577. X * DESCRIPTION
  578. X *
  579. X *    Addname adds the name given to the name list.  Memory for the
  580. X *    namelist structure is dynamically allocated.  If the space for 
  581. X *    the structure cannot be allocated, then the program will exit
  582. X *    the an out of memory error message and a non-zero return code
  583. X *    will be returned to the caller.
  584. X *
  585. X * PARAMETERS
  586. X *
  587. X *    char *name    - A pointer to the name to add to the list
  588. X */
  589. X
  590. X#ifdef __STDC__
  591. X
  592. Xvoid add_name(char *name)
  593. X
  594. X#else
  595. X    
  596. Xvoid add_name(name)
  597. Xchar           *name;        /* pointer to name */
  598. X
  599. X#endif
  600. X{
  601. X    int             i;        /* Length of string */
  602. X    struct nm_list *p;        /* Current struct pointer */
  603. X
  604. X    i = strlen(name);
  605. X    p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
  606. X    if (!p) {
  607. X    fatal("cannot allocate memory for namelist entry\n");
  608. X    }
  609. X    p->next = (struct nm_list *) NULL;
  610. X    p->length = i;
  611. X    strncpy(p->name, name, i);
  612. X    p->name[i] = '\0';        /* Null term */
  613. X    p->found = 0;
  614. X    p->firstch = isalpha(name[0]);
  615. X    if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
  616. X        p->regexp = 1;
  617. X    }
  618. X    if (namelast) {
  619. X    namelast->next = p;
  620. X    }
  621. X    namelast = p;
  622. X    if (!namelist) {
  623. X    namelist = p;
  624. X    }
  625. X}
  626. X
  627. X
  628. X/* name_match - match a name from an archive with a name from the namelist 
  629. X *
  630. X * DESCRIPTION
  631. X *
  632. X *    Name_match attempts to find a name pointed at by p in the namelist.
  633. X *    If no namelist is available, then all filenames passed in are
  634. X *    assumed to match the filename criteria.  Name_match knows how to
  635. X *    match names with regular expressions, etc.
  636. X *
  637. X * PARAMETERS
  638. X *
  639. X *    char    *p    - the name to match
  640. X *
  641. X * RETURNS
  642. X *
  643. X *    Returns 1 if the name is in the namelist, or no name list is
  644. X *    available, otherwise returns 0
  645. X *
  646. X */
  647. X
  648. X#ifdef __STDC__
  649. X
  650. Xint name_match(char *p)
  651. X
  652. X#else
  653. X    
  654. Xint name_match(p)
  655. Xchar           *p;
  656. X
  657. X#endif
  658. X{
  659. X    struct nm_list *nlp;
  660. X    int             len;
  661. X
  662. X    if ((nlp = namelist) == 0) {/* Empty namelist is easy */
  663. X    return (1);
  664. X    }
  665. X    len = strlen(p);
  666. X    for (; nlp != 0; nlp = nlp->next) {
  667. X    /* If first chars don't match, quick skip */
  668. X    if (nlp->firstch && nlp->name[0] != p[0]) {
  669. X        continue;
  670. X    }
  671. X    /* Regular expressions */
  672. X    if (nlp->regexp) {
  673. X        if (wildmat(nlp->name, p)) {
  674. X        nlp->found = 1;    /* Remember it matched */
  675. X        return (1);    /* We got a match */
  676. X        }
  677. X        continue;
  678. X    }
  679. X    /* Plain Old Strings */
  680. X    if (nlp->length <= len    /* Archive len >= specified */
  681. X        && (p[nlp->length] == '\0' || p[nlp->length] == '/')
  682. X        && strncmp(p, nlp->name, nlp->length) == 0) {
  683. X        /* Name compare */
  684. X        nlp->found = 1;    /* Remember it matched */
  685. X        return (1);        /* We got a match */
  686. X    }
  687. X    }
  688. X    return (0);
  689. X}
  690. X
  691. X
  692. X/* names_notfound - print names of files in namelist that were not found 
  693. X *
  694. X * DESCRIPTION
  695. X *
  696. X *    Names_notfound scans through the namelist for any files which were
  697. X *    named, but for which a matching file was not processed by the
  698. X *    archive.  Each of the files is listed on the standard error.
  699. X *
  700. X */
  701. X
  702. X#ifdef __STDC__
  703. X
  704. Xvoid names_notfound(void)
  705. X
  706. X#else
  707. X    
  708. Xvoid names_notfound()
  709. X
  710. X#endif
  711. X{
  712. X    struct nm_list *nlp;
  713. X
  714. X    for (nlp = namelist; nlp != 0; nlp = nlp->next) {
  715. X    if (!nlp->found) {
  716. X        fprintf(stderr, "%s: %s not found in archive\n",
  717. X               myname, nlp->name);
  718. X    }
  719. X    free(nlp);
  720. X    }
  721. X    namelist = (struct nm_list *) NULL;
  722. X    namelast = (struct nm_list *) NULL;
  723. X}
  724. X
  725. X
  726. X/* name_init - set up to gather file names 
  727. X *
  728. X * DESCRIPTION
  729. X *
  730. X *    Name_init sets up the namelist pointers so that we may access the
  731. X *    command line arguments.  At least the first item of the command
  732. X *    line (argv[0]) is assumed to be stripped off, prior to the
  733. X *    name_init call.
  734. X *
  735. X * PARAMETERS
  736. X *
  737. X *    int    argc    - number of items in argc
  738. X *    char    **argv    - pointer to the command line arguments
  739. X */
  740. X
  741. X#ifdef __STDC__
  742. X
  743. Xvoid name_init(int argc, char **argv)
  744. X
  745. X#else
  746. X    
  747. Xvoid name_init(argc, argv)
  748. Xint             argc;
  749. Xchar          **argv;
  750. X
  751. X#endif
  752. X{
  753. X    /* Get file names from argv, after options. */
  754. X    n_argc = argc;
  755. X    n_argv = argv;
  756. X}
  757. X
  758. X
  759. X/* name_next - get the next name from argv or the name file. 
  760. X *
  761. X * DESCRIPTION
  762. X *
  763. X *    Name next finds the next name which is to be processed in the
  764. X *    archive.  If the named file is a directory, then the directory
  765. X *    is recursively traversed for additional file names.  Directory
  766. X *    names and locations within the directory are kept track of by
  767. X *    using a directory stack.  See the pushdir/popdir function for
  768. X *    more details.
  769. X *
  770. X *     The names come from argv, after options or from the standard input.  
  771. X *
  772. X * PARAMETERS
  773. X *
  774. X *    name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
  775. X *    statbuf - a pointer to a stat structure
  776. X *
  777. X * RETURNS
  778. X *
  779. X *    Returns -1 if there are no names left, (e.g. EOF), otherwise returns 
  780. X *    0 
  781. X */
  782. X
  783. X#ifdef __STDC__
  784. X
  785. Xint name_next(char *name, Stat *statbuf)
  786. X
  787. X#else
  788. X    
  789. Xint name_next(name, statbuf)
  790. Xchar           *name;
  791. XStat           *statbuf;
  792. X
  793. X#endif
  794. X{
  795. X    int             err = -1;
  796. X    static int      in_subdir = 0;
  797. X    static DIR     *dirp;
  798. X    struct dirent  *d;
  799. X    static struct dirinfo *curr_dir;
  800. X    int            len;
  801. X
  802. X    do {
  803. X    if (names_from_stdin) {
  804. X        if (lineget(stdin, name) < 0) {
  805. X        return (-1);
  806. X        }
  807. X        if (nameopt(name) < 0) {
  808. X        continue;
  809. X        }
  810. X    } else {
  811. X        if (in_subdir) {
  812. X        if ((d = readdir(dirp)) != NULL) {
  813. X            /* Skip . and .. */
  814. X            if (strcmp(d->d_name, ".") == 0 ||
  815. X                strcmp(d->d_name, "..") == 0) {
  816. X                continue;
  817. X            }
  818. X            if (strlen(d->d_name) + 
  819. X            strlen(curr_dir->dirname) >= PATH_MAX) {
  820. X            warn("name too long", d->d_name);
  821. X            continue;
  822. X            }
  823. X            strcpy(name, curr_dir->dirname);
  824. X            strcat(name, d->d_name);
  825. X        } else {
  826. X            closedir(dirp);
  827. X            in_subdir--;
  828. X            curr_dir = popdir();
  829. X            if (in_subdir) {
  830. X            errno = 0;
  831. X            if ((dirp = opendir(curr_dir->dirname)) == NULL) {
  832. X                warn(curr_dir->dirname, "error opening directory (1)");
  833. X                in_subdir--;
  834. X            }
  835. X            seekdir(dirp, curr_dir->where);
  836. X            }
  837. X            continue;
  838. X        }
  839. X        } else if (optind >= n_argc) {
  840. X        return (-1);
  841. X        } else {
  842. X        strcpy(name, n_argv[optind++]);
  843. X        }
  844. X    }
  845. X    if ((err = LSTAT(name, statbuf)) < 0) {
  846. X        warn(name, syserr());
  847. X        continue;
  848. X    }
  849. X    if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
  850. X        if (in_subdir) {
  851. X        curr_dir->where = telldir(dirp);
  852. X        pushdir(curr_dir);
  853. X        close(dirp);
  854. X        } 
  855. X        in_subdir++;
  856. X
  857. X        /* Build new prototype name */
  858. X        if ((curr_dir = (struct dirinfo *) 
  859. X            mem_get(sizeof(struct dirinfo))) == NULL) {
  860. X        exit(2);
  861. X        }
  862. X        strcpy(curr_dir->dirname, name);
  863. X        len = strlen(curr_dir->dirname);
  864. X        while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
  865. X        len--;        /* Delete trailing slashes */
  866. X        }
  867. X        curr_dir->dirname[len++] = '/';    /* Now add exactly one back */
  868. X        curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
  869. X
  870. X        errno = 0;
  871. X        if ((dirp = opendir(curr_dir->dirname)) == NULL) {
  872. X        warn(curr_dir->dirname, "error opening directory (2)");
  873. X        }
  874. X    }
  875. X    } while (err < 0);
  876. X    return (0);
  877. X}
  878. X
  879. X
  880. X/* name_gather - gather names in a list for scanning. 
  881. X *
  882. X * DESCRIPTION
  883. X *
  884. X *    Name_gather takes names from the command line and adds them to
  885. X *    the name list.
  886. X *
  887. X * FIXME
  888. X *
  889. X *     We could hash the names if we really care about speed here.
  890. X */
  891. X
  892. X#ifdef __STDC__
  893. X
  894. Xvoid name_gather(void)
  895. X
  896. X#else
  897. X    
  898. Xvoid name_gather()
  899. X
  900. X#endif
  901. X{
  902. X     while (optind < n_argc) { 
  903. X     add_name(n_argv[optind++]); 
  904. X     } 
  905. X}
  906. X
  907. X
  908. Xstatic struct dirinfo *stack_head = NULL;
  909. X
  910. X
  911. X/* pushdir - pushes a directory name on the directory stack
  912. X *
  913. X * DESCRIPTION
  914. X *
  915. X *    The pushdir function puses the directory structure which is pointed
  916. X *    to by "info" onto a stack for later processing.  The information
  917. X *    may be retrieved later with a call to popdir().
  918. X *
  919. X * PARAMETERS
  920. X *
  921. X *    dirinfo    *info    - pointer to directory structure to save
  922. X */
  923. X
  924. X#ifdef __STDC__
  925. X
  926. Xstatic void pushdir(struct dirinfo *info)
  927. X
  928. X#else
  929. X    
  930. Xstatic void pushdir(info)
  931. Xstruct dirinfo    *info;
  932. X
  933. X#endif
  934. X{
  935. X    if  (stack_head == NULL) {
  936. X    stack_head = info;
  937. X    stack_head->next = NULL;
  938. X    } else {
  939. X    info->next = stack_head;
  940. X    stack_head = info;
  941. X    } 
  942. X}
  943. X
  944. X
  945. X/* popdir - pop a directory structure off the directory stack.
  946. X *
  947. X * DESCRIPTION
  948. X *
  949. X *    The popdir function pops the most recently pushed directory
  950. X *    structure off of the directory stack and returns it to the calling
  951. X *    function.
  952. X *
  953. X * RETURNS
  954. X *
  955. X *    Returns a pointer to the most recently pushed directory structure
  956. X *    or NULL if the stack is empty.
  957. X */
  958. X
  959. X#ifdef __STDC__
  960. X
  961. Xstatic struct dirinfo *popdir(void)
  962. X
  963. X#else
  964. X    
  965. Xstatic struct dirinfo *popdir()
  966. X
  967. X#endif
  968. X{
  969. X    struct dirinfo    *tmp;
  970. X
  971. X    if (stack_head == NULL) {
  972. X    return(NULL);
  973. X    } else {
  974. X    tmp = stack_head;
  975. X    stack_head = stack_head->next;
  976. X    }
  977. X    return(tmp);
  978. X}
  979. END_OF_namelist.c
  980. if test 11056 -ne `wc -c <namelist.c`; then
  981.     echo shar: \"namelist.c\" unpacked with wrong size!
  982. fi
  983. # end of overwriting check
  984. fi
  985. if test -f pax.c -a "${1}" != "-c" ; then 
  986.   echo shar: Will not over-write existing file \"pax.c\"
  987. else
  988. echo shar: Extracting \"pax.c\" \(13026 characters\)
  989. sed "s/^X//" >pax.c <<'END_OF_pax.c'
  990. X/* $Source: /u/mark/src/pax/RCS/pax.c,v $
  991. X *
  992. X * $Revision: 1.1 $
  993. X *
  994. X * DESCRIPTION
  995. X *
  996. X *    Pax is the archiver described in IEEE P1003.2.  It is an archiver
  997. X *    which understands both tar and cpio archives and has a new interface.
  998. X *
  999. X * SYNOPSIS
  1000. X *
  1001. X *    pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
  1002. X *    pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
  1003. X *    pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...]
  1004. X *           [-t device][-x format][pathname...]
  1005. X *    pax -r -w [-ilmopuvy][-s replstr][pathname...] directory
  1006. X *
  1007. X * DESCRIPTION
  1008. X *
  1009. X *     PAX - POSIX conforming tar and cpio archive handler.  This
  1010. X *    program implements POSIX conformant versions of tar, cpio and pax
  1011. X *    archive handlers for UNIX.  These handlers have defined befined
  1012. X *    by the IEEE P1003.2 commitee.
  1013. X *
  1014. X * COMPILATION
  1015. X *
  1016. X *    A number of different compile time configuration options are
  1017. X *    available, please see the Makefile and config.h for more details.
  1018. X *
  1019. X * AUTHOR
  1020. X *
  1021. X *     Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  1022. X *
  1023. X *
  1024. X * Sponsored by The USENIX Association for public distribution. 
  1025. X *
  1026. X * Copyright (c) 1989 Mark H. Colburn.
  1027. X * All rights reserved.
  1028. X *
  1029. X * Redistribution and use in source and binary forms are permitted
  1030. X * provided that the above copyright notice is duplicated in all such 
  1031. X * forms and that any documentation, advertising materials, and other 
  1032. X * materials related to such distribution and use acknowledge that the 
  1033. X * software was developed * by Mark H. Colburn and sponsored by The 
  1034. X * USENIX Association. 
  1035. X *
  1036. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1037. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1038. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1039. X *
  1040. X * $Log:    pax.c,v $
  1041. X * Revision 1.1  88/12/23  18:02:23  mark
  1042. X * Initial revision
  1043. X * 
  1044. X */
  1045. X
  1046. X#ifndef lint
  1047. Xstatic char *ident = "$Id: pax.c,v 1.1 88/12/23 18:02:23 mark Rel $";
  1048. Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  1049. X#endif /* ! lint */
  1050. X
  1051. X
  1052. X/* Headers */
  1053. X
  1054. X#define NO_EXTERN
  1055. X#include "pax.h"
  1056. X
  1057. X
  1058. X/* Globally Available Identifiers */
  1059. X
  1060. Xchar           *ar_file;        /* File containing name of archive */
  1061. Xchar           *bufend;            /* End of data within archive buffer */
  1062. Xchar           *bufstart;        /* Archive buffer */
  1063. Xchar           *bufidx;            /* Archive buffer index */
  1064. Xchar           *myname;            /* name of executable (argv[0]) */
  1065. Xchar          **n_argv;            /* Argv used by name routines */
  1066. Xint             n_argc;            /* Argc used by name routines */
  1067. Xint             archivefd;        /* Archive file descriptor */
  1068. Xint             blocking;        /* Size of each block, in records */
  1069. Xint             gid;            /* Group ID */
  1070. Xint             head_standard;        /* true if archive is POSIX format */
  1071. Xint             ar_interface;        /* defines interface we are using */
  1072. Xint             ar_format;        /* defines current archve format */
  1073. Xint             mask;            /* File creation mask */
  1074. Xint             ttyf;            /* For interactive queries */
  1075. Xint             uid;            /* User ID */
  1076. Xint        names_from_stdin;    /* names for files are from stdin */
  1077. XOFFSET          total;            /* Total number of bytes transferred */
  1078. Xshort           f_access_time;        /* Reset access times of input files */
  1079. Xshort           areof;            /* End of input volume reached */
  1080. Xshort           f_create_dirs;        /* Create missing directories */
  1081. Xshort           f_append;        /* Add named files to end of archive */
  1082. Xshort           f_create;        /* create a new archive */
  1083. Xshort           f_extract;        /* Extract named files from archive */
  1084. Xshort           f_follow_links;        /* follow symbolic links */
  1085. Xshort           f_interactive;        /* Interactivly extract files */
  1086. Xshort           f_linksleft;        /* Report on unresolved links */
  1087. Xshort           f_list;            /* List files on the archive */
  1088. Xshort           f_modified;        /* Don't restore modification times */
  1089. Xshort           f_verbose;        /* Turn on verbose mode */
  1090. Xshort        f_link;            /* link files where possible */
  1091. Xshort        f_owner;        /* extract files as the user */
  1092. Xshort        f_pass;            /* pass files between directories */
  1093. Xshort           f_newer;        /* append files to archive if newer */
  1094. Xshort        f_disposition;        /* ask for file disposition */
  1095. Xshort           f_reverse_match;    /* Reverse sense of pattern match */
  1096. Xshort           f_modification_time;    /* Retain file modification time */
  1097. Xshort           f_unconditional;    /* Copy unconditionally */
  1098. Xtime_t          now = 0;        /* Current time */
  1099. Xuint            arvolume;        /* Volume number */
  1100. Xuint            blocksize = BLOCKSIZE;    /* Archive block size */
  1101. XFILE           *msgfile;        /* message outpu file stdout/stderr */
  1102. XReplstr        *rplhead = NULL;        /* pointer to head of replstr list */
  1103. XReplstr        *rpltail;        /* pointer to tail of replstr list */
  1104. X
  1105. X
  1106. X/* Function Prototypes */
  1107. X
  1108. X#ifdef __STDC__
  1109. X
  1110. Xstatic void     usage(void);
  1111. Xstatic OFFSET   pax_optsize(char *);
  1112. X
  1113. X#else /* !__STDC__ */
  1114. X
  1115. Xstatic void     usage();
  1116. Xstatic OFFSET   pax_optsize();
  1117. X
  1118. X#endif /* __STDC__ */
  1119. X
  1120. X
  1121. X/* main - main routine for handling all archive formats.
  1122. X *
  1123. X * DESCRIPTION
  1124. X *
  1125. X *     Set up globals and call the proper interface as specified by the user.
  1126. X *
  1127. X * PARAMETERS
  1128. X *
  1129. X *    int argc    - count of user supplied arguments
  1130. X *    char **argv    - user supplied arguments 
  1131. X *
  1132. X * RETURNS
  1133. X *
  1134. X *    Returns an exit code of 0 to the parent process.
  1135. X */
  1136. X
  1137. X#ifdef __STDC__
  1138. X
  1139. Xint main(int argc, char **argv)
  1140. X
  1141. X#else
  1142. X
  1143. Xint main(argc, argv)
  1144. Xint             argc;
  1145. Xchar          **argv;
  1146. X
  1147. X#endif
  1148. X{
  1149. X    /* strip the pathname off of the name of the executable */
  1150. X    if ((myname = strrchr(argv[0], '/')) != (char *)NULL) {
  1151. X    myname++;
  1152. X    } else {
  1153. X    myname = argv[0];
  1154. X    }
  1155. X
  1156. X    /* set upt for collecting other command line arguments */
  1157. X    name_init(argc, argv);
  1158. X
  1159. X    /* get all our necessary information */
  1160. X    mask = umask(0);
  1161. X    uid = getuid();
  1162. X    gid = getgid();
  1163. X    now = time((time_t *) 0);
  1164. X
  1165. X    /* open terminal for interactive queries */
  1166. X    ttyf = open_tty();
  1167. X
  1168. X    if (strcmp(myname, "tar")==0) {
  1169. X    do_tar(argc, argv);
  1170. X    } else if (strcmp(myname, "cpio")==0) {
  1171. X    do_cpio(argc, argv);
  1172. X    } else {
  1173. X    do_pax(argc, argv);
  1174. X    }
  1175. X    exit(0);
  1176. X    /* NOTREACHED */
  1177. X}
  1178. X
  1179. X
  1180. X/* do_pax - provide a PAX conformant user interface for archive handling
  1181. X *
  1182. X * DESCRIPTION
  1183. X *
  1184. X *    Process the command line parameters given, doing some minimal sanity
  1185. X *    checking, and then launch the specified archiving functions.
  1186. X *
  1187. X * PARAMETERS
  1188. X *
  1189. X *    int ac        - A count of arguments in av.  Should be passed argc 
  1190. X *              from main
  1191. X *    char **av        - A pointer to an argument list.  Should be passed 
  1192. X *              argv from main
  1193. X *
  1194. X * RETURNS
  1195. X *
  1196. X *    Normally returns 0.  If an error occurs, -1 is returned 
  1197. X *    and state is set to reflect the error.
  1198. X *
  1199. X */
  1200. X
  1201. X#ifdef __STDC__
  1202. X
  1203. Xint do_pax(int ac, char **av)
  1204. X
  1205. X#else
  1206. X
  1207. Xint do_pax(ac, av)
  1208. Xint             ac;        /* argument counter */
  1209. Xchar          **av;        /* arguments */
  1210. X
  1211. X#endif
  1212. X{
  1213. X    int             c;
  1214. X    char       *dirname;
  1215. X    Stat        st;
  1216. X
  1217. X    /* default input/output file for PAX is STDIN/STDOUT */
  1218. X    ar_file = "-";
  1219. X
  1220. X    /*
  1221. X     * set up the flags to reflect the default pax inteface.  Unfortunately
  1222. X     * the pax interface has several options which are completely opposite
  1223. X     * of the tar and/or cpio interfaces...
  1224. X     */
  1225. X    f_unconditional = 1;
  1226. X    f_modification_time = 1;
  1227. X    f_create_dirs = 1;
  1228. X    f_list = 1;
  1229. X    blocksize = 0;
  1230. X    blocking = 0;
  1231. X    ar_interface = PAX;
  1232. X    ar_format = TAR;    /* default interface if none given for -w */
  1233. X    msgfile=stdout;
  1234. X
  1235. X    while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) {
  1236. X    switch (c) {
  1237. X    case 'a':
  1238. X        f_append = 1;
  1239. X        f_list = 0;
  1240. X        break;
  1241. X    case 'b':
  1242. X        if ((blocksize = pax_optsize(optarg)) == 0) {
  1243. X        fatal("Bad block size");
  1244. X        }
  1245. X        break;
  1246. X    case 'c':
  1247. X        f_reverse_match = 1;
  1248. X        break;
  1249. X    case 'd':
  1250. X        f_create_dirs = 0;
  1251. X        break;
  1252. X    case 'f':
  1253. X        if (blocksize == 0) {
  1254. X        blocking = 1;
  1255. X        blocksize = 1 * BLOCKSIZE;
  1256. X        }
  1257. X        ar_file = optarg;
  1258. X        break;
  1259. X    case 'i':
  1260. X        f_interactive = 1;
  1261. X        break;
  1262. X    case 'l':
  1263. X        f_link = 1;
  1264. X        break;
  1265. X    case 'm':
  1266. X        f_modification_time = 0;
  1267. X        break;
  1268. X    case 'o':
  1269. X        f_owner = 1;
  1270. X        break;
  1271. X    case 'p':
  1272. X        f_access_time = 1;
  1273. X        break;
  1274. X    case 'r':
  1275. X        if (f_create) {
  1276. X        f_create = 0;
  1277. X        f_pass = 1;
  1278. X        } else {
  1279. X        f_list = 0;
  1280. X        f_extract = 1;
  1281. X        } 
  1282. X        msgfile=stderr;
  1283. X        break;
  1284. X    case 's':
  1285. X        add_replstr(optarg);
  1286. X        break;
  1287. X    case 't':
  1288. X        if (blocksize == 0) {
  1289. X        blocking = 1;
  1290. X        blocksize = 10 * BLOCKSIZE;
  1291. X        }
  1292. X        ar_file = optarg;
  1293. X        break;
  1294. X    case 'u':
  1295. X        f_unconditional = 1;
  1296. X        break;
  1297. X    case 'v':
  1298. X        f_verbose = 1;
  1299. X        break;
  1300. X    case 'w':
  1301. X        if (f_extract) {
  1302. X        f_extract = 0;
  1303. X        f_pass = 1;
  1304. X        } else {
  1305. X        f_list = 0;
  1306. X        f_create = 1;
  1307. X        } 
  1308. X        msgfile=stderr;
  1309. X        break;
  1310. X    case 'x':
  1311. X        if (strcmp(optarg, "ustar") == 0) {
  1312. X        ar_format = TAR;
  1313. X        } else if (strcmp(optarg, "cpio") == 0) {
  1314. X        ar_format = CPIO;
  1315. X        } else {
  1316. X        usage();
  1317. X        }
  1318. X        break;
  1319. X    case 'y':
  1320. X        f_disposition = 1;
  1321. X        break;
  1322. X    default:
  1323. X        usage();
  1324. X    }
  1325. X    }
  1326. X
  1327. X    if (blocksize == 0) {
  1328. X    blocking = 1;
  1329. X    blocksize = blocking * BLOCKSIZE;
  1330. X    }
  1331. X    buf_allocate((OFFSET) blocksize);
  1332. X
  1333. X    if (f_extract || f_list) {
  1334. X    open_archive(AR_READ);
  1335. X    get_archive_type();
  1336. X    read_archive();
  1337. X    } else if (f_create) {
  1338. X    if (optind >= n_argc) {
  1339. X        names_from_stdin++;        /* args from stdin */
  1340. X    }
  1341. X    open_archive(AR_WRITE);
  1342. X    create_archive();
  1343. X    } else if (f_append) {
  1344. X    open_archive(AR_APPEND);
  1345. X    get_archive_type();
  1346. X    append_archive();
  1347. X    } else if (f_pass && optind < n_argc) {
  1348. X    dirname = n_argv[--n_argc];
  1349. X    if (LSTAT(dirname, &st) < 0) {
  1350. X        fatal(syserr());
  1351. X    }
  1352. X    if ((st.sb_mode & S_IFMT) != S_IFDIR) {
  1353. X        fatal("Not a directory");
  1354. X    }
  1355. X    if (optind >= n_argc) {
  1356. X        names_from_stdin++;        /* args from stdin */
  1357. X    }
  1358. X    pass(dirname);
  1359. X    } else {
  1360. X    usage();
  1361. X    }
  1362. X
  1363. X    return (0);
  1364. X}
  1365. X
  1366. X
  1367. X/* get_archive_type - determine input archive type from archive header
  1368. X *
  1369. X * DESCRIPTION
  1370. X *
  1371. X *     reads the first block of the archive and determines the archive 
  1372. X *    type from the data.  If the archive type cannot be determined, 
  1373. X *    processing stops, and a 1 is returned to the caller.  If verbose
  1374. X *    mode is on, then the archive type will be printed on the standard
  1375. X *    error device as it is determined.
  1376. X *
  1377. X * FIXME 
  1378. X *
  1379. X *    be able to understand TAR and CPIO magic numbers
  1380. X */
  1381. X
  1382. X#ifdef __STDC__
  1383. X
  1384. Xvoid get_archive_type(void)
  1385. X
  1386. X#else
  1387. X
  1388. Xvoid get_archive_type()
  1389. X
  1390. X#endif
  1391. X{
  1392. X    if (ar_read() != 0) {
  1393. X    fatal("Unable to determine archive type.");
  1394. X    }
  1395. X    if (strncmp(bufstart, "070707", 6) == 0) {
  1396. X    ar_format = CPIO;
  1397. X    if (f_verbose) {
  1398. X        fputs("CPIO format archive\n", stderr);
  1399. X    }
  1400. X    } else if (strncmp(&bufstart[257], "ustar", 5) == 0) {
  1401. X    ar_format = TAR;
  1402. X    if (f_verbose) {
  1403. X        fputs("USTAR format archive\n", stderr);
  1404. X    }
  1405. X    } else {
  1406. X    ar_format = TAR;
  1407. X    }
  1408. X}
  1409. X
  1410. X
  1411. X/* pax_optsize - interpret a size argument
  1412. X *
  1413. X * DESCRIPTION
  1414. X *
  1415. X *     Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes.  
  1416. X *     Also handles simple expressions containing '+' for addition.
  1417. X *
  1418. X * PARAMETERS
  1419. X *
  1420. X *    char     *str    - A pointer to the string to interpret
  1421. X *
  1422. X * RETURNS
  1423. X *
  1424. X *    Normally returns the value represented by the expression in the 
  1425. X *    the string.
  1426. X *
  1427. X * ERRORS
  1428. X *
  1429. X *    If the string cannot be interpretted, the program will fail, since
  1430. X *    the buffering will be incorrect.
  1431. X *
  1432. X */
  1433. X
  1434. X#ifdef __STDC__
  1435. X
  1436. Xstatic OFFSET pax_optsize(char *str)
  1437. X
  1438. X#else
  1439. X
  1440. Xstatic OFFSET pax_optsize(str)
  1441. Xchar           *str;        /* pointer to string to interpret */
  1442. X
  1443. X#endif
  1444. X{
  1445. X    char           *idx;
  1446. X    OFFSET          number;    /* temporary storage for current number */
  1447. X    OFFSET          result;    /* cumulative total to be returned to caller */
  1448. X
  1449. X    result = 0;
  1450. X    idx = str;
  1451. X    for (;;) {
  1452. X    number = 0;
  1453. X    while (*idx >= '0' && *idx <= '9')
  1454. X        number = number * 10 + *idx++ - '0';
  1455. X    switch (*idx++) {
  1456. X    case 'b':
  1457. X        result += number * 512;
  1458. X        continue;
  1459. X    case 'k':
  1460. X        result += number * 1024;
  1461. X        continue;
  1462. X    case 'm':
  1463. X        result += number * 1024 * 1024;
  1464. X        continue;
  1465. X    case '+':
  1466. X        result += number;
  1467. X        continue;
  1468. X    case '\0':
  1469. X        result += number;
  1470. X        break;
  1471. X    default:
  1472. X        break;
  1473. X    }
  1474. X    break;
  1475. X    }
  1476. X    if (*--idx) {
  1477. X    fatal("Unrecognizable value");
  1478. X    }
  1479. X    return (result);
  1480. X}
  1481. X
  1482. X
  1483. X/* usage - print a helpful message and exit
  1484. X *
  1485. X * DESCRIPTION
  1486. X *
  1487. X *    Usage prints out the usage message for the PAX interface and then
  1488. X *    exits with a non-zero termination status.  This is used when a user
  1489. X *    has provided non-existant or incompatible command line arguments.
  1490. X *
  1491. X * RETURNS
  1492. X *
  1493. X *    Returns an exit status of 1 to the parent process.
  1494. X *
  1495. X */
  1496. X
  1497. X#ifdef __STDC__
  1498. X
  1499. Xstatic void usage(void)
  1500. X
  1501. X#else
  1502. X
  1503. Xstatic void usage()
  1504. X
  1505. X#endif
  1506. X{
  1507. X    fprintf(stderr, "\
  1508. XUsage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
  1509. X    myname);
  1510. X    fprintf(stderr, "\
  1511. X       %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
  1512. X    myname);
  1513. X    fprintf(stderr, "\
  1514. X       %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n\
  1515. X       [-t device] [-x format] [pathname...]\n",
  1516. X    myname);
  1517. X    fprintf(stderr, "\
  1518. X       %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n",
  1519. X    myname);
  1520. X    exit(1);
  1521. X}
  1522. END_OF_pax.c
  1523. if test 13026 -ne `wc -c <pax.c`; then
  1524.     echo shar: \"pax.c\" unpacked with wrong size!
  1525. fi
  1526. # end of overwriting check
  1527. fi
  1528. if test -f pax.h -a "${1}" != "-c" ; then 
  1529.   echo shar: Will not over-write existing file \"pax.h\"
  1530. else
  1531. echo shar: Extracting \"pax.h\" \(9317 characters\)
  1532. sed "s/^X//" >pax.h <<'END_OF_pax.h'
  1533. X/* $Source: /u/mark/src/pax/RCS/pax.h,v $
  1534. X *
  1535. X * $Revision: 1.1 $
  1536. X *
  1537. X * pax.h - defnitions for entire program
  1538. X *
  1539. X * DESCRIPTION
  1540. X *
  1541. X *    This file contains most all of the definitions required by the PAX
  1542. X *    software.  This header is included in every source file.
  1543. X *
  1544. X * AUTHOR
  1545. X *
  1546. X *     Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  1547. X *
  1548. X * Sponsored by The USENIX Association for public distribution. 
  1549. X *
  1550. X * Copyright (c) 1989 Mark H. Colburn.
  1551. X * All rights reserved.
  1552. X *
  1553. X * Redistribution and use in source and binary forms are permitted
  1554. X * provided that the above copyright notice and this paragraph are
  1555. X * duplicated in all such forms and that any documentation,
  1556. X * advertising materials, and other materials related to such
  1557. X * distribution and use acknowledge that the software was developed
  1558. X * by Mark H. Colburn and sponsored by The USENIX Association. 
  1559. X *
  1560. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1561. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1562. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1563. X */
  1564. X
  1565. X#ifndef _PAX_H
  1566. X#define _PAX_H
  1567. X
  1568. X/* Headers */
  1569. X
  1570. X#include "config.h"
  1571. X#include "limits.h"
  1572. X#include <stdio.h>
  1573. X#include <errno.h>
  1574. X#include <signal.h>
  1575. X#include <ctype.h>
  1576. X#include <sys/types.h>
  1577. X#include <sys/ioctl.h>
  1578. X#include <sys/stat.h>
  1579. X#include "regexp.h"
  1580. X
  1581. X#if defined(DIRENT) || defined(_POSIX_SOURCE)
  1582. X# ifdef PAXDIR
  1583. X#  include "paxdir.h"
  1584. X# else
  1585. X#  include <dirent.h>
  1586. X# endif
  1587. X#else
  1588. X# include <sys/dir.h>
  1589. X# define dirent direct
  1590. X#endif
  1591. X
  1592. X#ifndef    major
  1593. X#   include <sys/sysmacros.h>
  1594. X#endif                /* major */
  1595. X
  1596. X#ifdef    SYSTIME
  1597. X#   include <sys/time.h>
  1598. X#else                /* SYSTIME */
  1599. X#   include <time.h>
  1600. X#endif                /* SYSTIME */
  1601. X
  1602. X#ifndef V7
  1603. X#   include <fcntl.h>
  1604. X#endif
  1605. X
  1606. X#ifdef XENIX
  1607. X#   include <sys/inode.h>
  1608. X#endif
  1609. X
  1610. X#include <pwd.h>
  1611. X#include <grp.h>
  1612. X#include <sys/file.h>
  1613. X
  1614. X/* Defines */
  1615. X
  1616. X#define    STDIN    0        /* Standard input  file descriptor */
  1617. X#define    STDOUT    1        /* Standard output file descriptor */
  1618. X
  1619. X/*
  1620. X * Open modes; there is no <fcntl.h> with v7 UNIX and other versions of
  1621. X * UNIX may not have all of these defined...
  1622. X */
  1623. X
  1624. X#ifndef O_RDONLY
  1625. X#   define    O_RDONLY    0
  1626. X#endif
  1627. X
  1628. X#ifndef O_WRONLY
  1629. X#   define    O_WRONLY    1
  1630. X#endif
  1631. X
  1632. X#ifndef O_RDWR
  1633. X#   define    O_WRONLY    2
  1634. X#endif
  1635. X
  1636. X#ifndef    O_BINARY
  1637. X#   define    O_BINARY    0
  1638. X#endif
  1639. X
  1640. X#ifndef NULL
  1641. X#   define     NULL         0
  1642. X#endif
  1643. X
  1644. X#define TMAGIC        "ustar"        /* ustar and a null */
  1645. X#define TMAGLEN        6
  1646. X#define TVERSION    "00"        /* 00 and no null */
  1647. X#define TVERSLEN    2
  1648. X
  1649. X/* Values used in typeflag field */
  1650. X#define REGTYPE        '0'        /* Regular File */
  1651. X#define AREGTYPE    '\0'        /* Regular File */
  1652. X#define LNKTYPE        '1'        /* Link */
  1653. X#define SYMTYPE        '2'        /* Reserved */
  1654. X#define CHRTYPE        '3'        /* Character Special File */
  1655. X#define BLKTYPE        '4'        /* Block Special File */
  1656. X#define DIRTYPE        '5'        /* Directory */
  1657. X#define FIFOTYPE    '6'        /* FIFO */
  1658. X#define CONTTYPE    '7'        /* Reserved */
  1659. X
  1660. X#define BLOCKSIZE    512    /* all output is padded to 512 bytes */
  1661. X#define    uint    unsigned int    /* Not always in types.h */
  1662. X#define    ushort    unsigned short    /* Not always in types.h */
  1663. X#define    BLOCK    5120        /* Default archive block size */
  1664. X#define    H_COUNT    10        /* Number of items in ASCII header */
  1665. X#define    H_PRINT    "%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo"
  1666. X#define    H_SCAN    "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6o%11lo"
  1667. X#define    H_STRLEN 70        /* ASCII header string length */
  1668. X#define    M_ASCII "070707"    /* ASCII magic number */
  1669. X#define    M_BINARY 070707        /* Binary magic number */
  1670. X#define    M_STRLEN 6        /* ASCII magic number length */
  1671. X#define    PATHELEM 256        /* Pathname element count limit */
  1672. X#define    S_IFSHF    12        /* File type shift (shb in stat.h) */
  1673. X#define    S_IPERM    07777        /* File permission bits (shb in stat.h) */
  1674. X#define    S_IPEXE    07000        /* Special execution bits (shb in stat.h) */
  1675. X#define    S_IPOPN    0777        /* Open access bits (shb in stat.h) */
  1676. X
  1677. X/*
  1678. X * Trailer pathnames. All must be of the same length. 
  1679. X */
  1680. X#define    TRAILER    "TRAILER!!!"    /* Archive trailer (cpio compatible) */
  1681. X#define    TRAILZ    11        /* Trailer pathname length (including null) */
  1682. X
  1683. X#include "port.h"
  1684. X
  1685. X
  1686. X#define    TAR        1
  1687. X#define    CPIO        2
  1688. X#define    PAX        3
  1689. X
  1690. X#define AR_READ     0
  1691. X#define AR_WRITE     1
  1692. X#define AR_EXTRACT    2
  1693. X#define AR_APPEND     4
  1694. X
  1695. X/*
  1696. X * Header block on tape. 
  1697. X */
  1698. X#define    NAMSIZ        100
  1699. X#define    PFIXSIZ        155
  1700. X#define    TUNMLEN        32
  1701. X#define    TGNMLEN        32
  1702. X
  1703. X/* The checksum field is filled with this while the checksum is computed. */
  1704. X#define    CHKBLANKS    "        "    /* 8 blanks, no null */
  1705. X
  1706. X/*
  1707. X * Exit codes from the "tar" program 
  1708. X */
  1709. X#define    EX_SUCCESS    0    /* success! */
  1710. X#define    EX_ARGSBAD    1    /* invalid args */
  1711. X#define    EX_BADFILE    2    /* invalid filename */
  1712. X#define    EX_BADARCH    3    /* bad archive */
  1713. X#define    EX_SYSTEM    4    /* system gave unexpected error */
  1714. X
  1715. X#define    ROUNDUP(a,b)     (((a) % (b)) == 0 ? (a) : ((a) + ((b) - ((a) % (b)))))
  1716. X
  1717. X/*
  1718. X * Mininum value. 
  1719. X */
  1720. X#define    MIN(a, b)    (((a) < (b)) ? (a) : (b))
  1721. X
  1722. X/*
  1723. X * Remove a file or directory. 
  1724. X */
  1725. X#define    REMOVE(name, asb) \
  1726. X    (((asb)->sb_mode & S_IFMT) == S_IFDIR ? rmdir(name) : unlink(name))
  1727. X
  1728. X/*
  1729. X * Cast and reduce to unsigned short. 
  1730. X */
  1731. X#define    USH(n)        (((ushort) (n)) & 0177777)
  1732. X
  1733. X
  1734. X/* Type Definitions */
  1735. X
  1736. X/*
  1737. X * Binary archive header (obsolete). 
  1738. X */
  1739. Xtypedef struct {
  1740. X    short           b_dev;    /* Device code */
  1741. X    ushort          b_ino;    /* Inode number */
  1742. X    ushort          b_mode;    /* Type and permissions */
  1743. X    ushort          b_uid;    /* Owner */
  1744. X    ushort          b_gid;    /* Group */
  1745. X    short           b_nlink;    /* Number of links */
  1746. X    short           b_rdev;    /* Real device */
  1747. X    ushort          b_mtime[2];    /* Modification time (hi/lo) */
  1748. X    ushort          b_name;    /* Length of pathname (with null) */
  1749. X    ushort          b_size[2];    /* Length of data */
  1750. X} Binary;
  1751. X
  1752. X/*
  1753. X * File status with symbolic links. Kludged to hold symbolic link pathname
  1754. X * within structure. 
  1755. X */
  1756. Xtypedef struct {
  1757. X    struct stat     sb_stat;
  1758. X    char            sb_link[PATH_MAX + 1];
  1759. X} Stat;
  1760. X
  1761. X#define    STAT(name, asb)        stat(name, &(asb)->sb_stat)
  1762. X#define    FSTAT(fd, asb)        fstat(fd, &(asb)->sb_stat)
  1763. X
  1764. X#define    sb_dev        sb_stat.st_dev
  1765. X#define    sb_ino        sb_stat.st_ino
  1766. X#define    sb_mode        sb_stat.st_mode
  1767. X#define    sb_nlink    sb_stat.st_nlink
  1768. X#define    sb_uid        sb_stat.st_uid
  1769. X#define    sb_gid        sb_stat.st_gid
  1770. X#define    sb_rdev        sb_stat.st_rdev
  1771. X#define    sb_size        sb_stat.st_size
  1772. X#define    sb_atime    sb_stat.st_atime
  1773. X#define    sb_mtime    sb_stat.st_mtime
  1774. X#define    sb_ctime    sb_stat.st_ctime
  1775. X
  1776. X#ifdef    S_IFLNK
  1777. X#    define    LSTAT(name, asb)    lstat(name, &(asb)->sb_stat)
  1778. X#    define    sb_blksize    sb_stat.st_blksize
  1779. X#    define    sb_blocks    sb_stat.st_blocks
  1780. X#else                /* S_IFLNK */
  1781. X/*
  1782. X * File status without symbolic links. 
  1783. X */
  1784. X#    define    LSTAT(name, asb)    stat(name, &(asb)->sb_stat)
  1785. X#endif                /* S_IFLNK */
  1786. X
  1787. X/*
  1788. X * Hard link sources. One or more are chained from each link structure. 
  1789. X */
  1790. Xtypedef struct name {
  1791. X    struct name    *p_forw;    /* Forward chain (terminated) */
  1792. X    struct name    *p_back;    /* Backward chain (circular) */
  1793. X    char           *p_name;    /* Pathname to link from */
  1794. X} Path;
  1795. X
  1796. X/*
  1797. X * File linking information. One entry exists for each unique file with with
  1798. X * outstanding hard links. 
  1799. X */
  1800. Xtypedef struct link {
  1801. X    struct link    *l_forw;    /* Forward chain (terminated) */
  1802. X    struct link    *l_back;    /* Backward chain (terminated) */
  1803. X    dev_t           l_dev;    /* Device */
  1804. X    ino_t           l_ino;    /* Inode */
  1805. X    ushort          l_nlink;    /* Unresolved link count */
  1806. X    OFFSET          l_size;    /* Length */
  1807. X    char       *l_name;    /* pathname to link from */
  1808. X    Path           *l_path;    /* Pathname which link to l_name */
  1809. X} Link;
  1810. X
  1811. X/*
  1812. X * Structure for ed-style replacement strings (-s option).
  1813. X*/
  1814. Xtypedef struct replstr {
  1815. X    regexp       *comp;    /* compiled regular expression */
  1816. X    char       *replace;    /* replacement string */
  1817. X    char        print;    /* >0 if we are to print replacement */
  1818. X    char        global;    /* >0 if we are to replace globally */
  1819. X    struct replstr *next;    /* pointer to next record */
  1820. X} Replstr;
  1821. X
  1822. X
  1823. X/*
  1824. X * This has to be included here to insure that all of the type 
  1825. X * delcarations are declared for the prototypes.
  1826. X */
  1827. X#include "func.h"
  1828. X
  1829. X
  1830. X#ifndef NO_EXTERN
  1831. X/* Globally Available Identifiers */
  1832. X
  1833. Xextern char    *ar_file;
  1834. Xextern char    *bufend;
  1835. Xextern char    *bufstart;
  1836. Xextern char    *bufidx;
  1837. Xextern char    *myname;
  1838. Xextern int      archivefd;
  1839. Xextern int      blocking;
  1840. Xextern uint     blocksize;
  1841. Xextern int      gid;
  1842. Xextern int      head_standard;
  1843. Xextern int      ar_interface;
  1844. Xextern int      ar_format;
  1845. Xextern int      mask;
  1846. Xextern int      ttyf;
  1847. Xextern int      uid;
  1848. Xextern OFFSET    total;
  1849. Xextern short    areof;
  1850. Xextern short    f_append;
  1851. Xextern short    f_create;
  1852. Xextern short    f_extract;
  1853. Xextern short    f_follow_links;
  1854. Xextern short    f_interactive;
  1855. Xextern short    f_linksleft;
  1856. Xextern short    f_list;
  1857. Xextern short    f_modified;
  1858. Xextern short    f_verbose;
  1859. Xextern short    f_link;
  1860. Xextern short    f_owner;
  1861. Xextern short    f_access_time;
  1862. Xextern short    f_pass;
  1863. Xextern short    f_pass;
  1864. Xextern short    f_disposition;
  1865. Xextern short    f_reverse_match;
  1866. Xextern short    f_modification_time;
  1867. Xextern short    f_create_dirs;
  1868. Xextern short    f_unconditional;
  1869. Xextern short    f_newer;
  1870. Xextern time_t   now;
  1871. Xextern uint     arvolume;
  1872. Xextern int    names_from_stdin;
  1873. Xextern Replstr *rplhead;
  1874. Xextern Replstr *rpltail;
  1875. Xextern char   **n_argv;
  1876. Xextern int      n_argc;
  1877. Xextern FILE    *msgfile;
  1878. X#endif /* NO_EXTERN */
  1879. X
  1880. Xextern char    *optarg;
  1881. Xextern int      optind;
  1882. Xextern int      sys_nerr;
  1883. Xextern char    *sys_errlist[];
  1884. Xextern int      errno;
  1885. X
  1886. X#endif /* _PAX_H */
  1887. END_OF_pax.h
  1888. if test 9317 -ne `wc -c <pax.h`; then
  1889.     echo shar: \"pax.h\" unpacked with wrong size!
  1890. fi
  1891. # end of overwriting check
  1892. fi
  1893. if test -f tar.c -a "${1}" != "-c" ; then 
  1894.   echo shar: Will not over-write existing file \"tar.c\"
  1895. else
  1896. echo shar: Extracting \"tar.c\" \(7881 characters\)
  1897. sed "s/^X//" >tar.c <<'END_OF_tar.c'
  1898. X/* $Source: /u/mark/src/pax/RCS/tar.c,v $
  1899. X *
  1900. X * $Revision: 1.1 $
  1901. X *
  1902. X * tar.c - tar specific functions for archive handling
  1903. X *
  1904. X * DESCRIPTION
  1905. X *
  1906. X *    These routines provide a tar conforming interface to the pax
  1907. X *    program.
  1908. X *
  1909. X * AUTHOR
  1910. X *
  1911. X *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  1912. X *
  1913. X * Sponsored by The USENIX Association for public distribution. 
  1914. X *
  1915. X * Copyright (c) 1989 Mark H. Colburn.
  1916. X * All rights reserved.
  1917. X *
  1918. X * Redistribution and use in source and binary forms are permitted
  1919. X * provided that the above copyright notice is duplicated in all such 
  1920. X * forms and that any documentation, advertising materials, and other 
  1921. X * materials related to such distribution and use acknowledge that the 
  1922. X * software was developed by Mark H. Colburn and sponsored by The 
  1923. X * USENIX Association. 
  1924. X *
  1925. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1926. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1927. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1928. X *
  1929. X * $Log:    tar.c,v $
  1930. X * Revision 1.1  88/12/23  18:02:38  mark
  1931. X * Initial revision
  1932. X * 
  1933. X */
  1934. X
  1935. X#ifndef lint
  1936. Xstatic char *ident = "$Id: tar.c,v 1.1 88/12/23 18:02:38 mark Rel $";
  1937. Xstatic char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.";
  1938. X#endif /* not lint */
  1939. X
  1940. X/* Headers */
  1941. X
  1942. X#include "pax.h"
  1943. X
  1944. X
  1945. X/* Defines */
  1946. X
  1947. X#define DEF_BLOCKING    20    /* default blocking factor for extract */
  1948. X
  1949. X
  1950. X/* Function Prototypes */
  1951. X
  1952. X#ifdef __STDC__
  1953. X
  1954. Xstatic int taropt(int , char **, char *);
  1955. Xstatic void usage(void);
  1956. X
  1957. X#else /* !__STDC__ */
  1958. X
  1959. Xstatic int taropt();
  1960. Xstatic void usage();
  1961. X
  1962. X#endif /* __STDC__ */
  1963. X
  1964. X
  1965. X/* do_tar - main routine for tar. 
  1966. X *
  1967. X * DESCRIPTION
  1968. X *
  1969. X *    Provides a tar interface to the PAX program.  All tar standard
  1970. X *    command line options are supported.
  1971. X *
  1972. X * PARAMETERS
  1973. X *
  1974. X *    int argc    - argument count (argc from main) 
  1975. X *    char **argv    - argument list (argv from main) 
  1976. X *
  1977. X * RETURNS
  1978. X *
  1979. X *    zero
  1980. X */
  1981. X
  1982. X#ifdef __STDC__
  1983. X
  1984. Xint do_tar(int argc, char **argv)
  1985. X
  1986. X#else
  1987. X
  1988. Xint do_tar(argc, argv)
  1989. Xint             argc;        /* argument count (argc from main) */
  1990. Xchar          **argv;        /* argument list (argv from main) */
  1991. X
  1992. X#endif
  1993. X{
  1994. X    int             c;        /* Option letter */
  1995. X
  1996. X    /* Set default option values */
  1997. X    names_from_stdin = 0;
  1998. X    ar_file = getenv("TAPE");    /* From environment, or */
  1999. X    if (ar_file == 0) {
  2000. X    ar_file = DEF_AR_FILE;    /* From Makefile */
  2001. X    }
  2002. X
  2003. X    /*
  2004. X     * set up the flags to reflect the default pax inteface.  Unfortunately
  2005. X     * the pax interface has several options which are completely opposite
  2006. X     * of the tar and/or cpio interfaces...
  2007. X     */
  2008. X    f_unconditional = 1;
  2009. X    f_modification_time = 1;
  2010. X    f_create_dirs = 1;
  2011. X    blocking = 0;
  2012. X    ar_interface = TAR;
  2013. X    ar_format = TAR;
  2014. X    msgfile=stdout;
  2015. X
  2016. X    /* Parse options */
  2017. X    while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
  2018. X    switch (c) {
  2019. X    case 'b':        /* specify blocking factor */
  2020. X        /* 
  2021. X         * FIXME - we should use a conversion routine that does
  2022. X         * some kind of reasonable error checking, but...
  2023. X         */
  2024. X        blocking = atoi(optarg);
  2025. X        break;
  2026. X    case 'c':        /* create a new archive */
  2027. X        f_create = 1;
  2028. X        break;
  2029. X    case 'f':        /* specify input/output file */
  2030. X        ar_file = optarg;
  2031. X        break;
  2032. X    case 'h':
  2033. X        f_follow_links = 1;    /* follow symbolic links */
  2034. X        break;
  2035. X    case 'l':        /* report unresolved links */
  2036. X        f_linksleft = 1;
  2037. X        break;
  2038. X    case 'm':        /* don't restore modification times */
  2039. X        f_modified = 1;
  2040. X        break;
  2041. X    case 'o':        /* take on user's group rather than
  2042. X                 * archives */
  2043. X        break;
  2044. X    case 'r':        /* named files are appended to archive */
  2045. X        f_append = 1;
  2046. X        break;
  2047. X    case 't':
  2048. X        f_list = 1;        /* list files in archive */
  2049. X        break;
  2050. X    case 'u':        /* named files are added to archive */
  2051. X        f_newer = 1;
  2052. X        break;
  2053. X    case 'v':        /* verbose mode */
  2054. X        f_verbose = 1;
  2055. X        break;
  2056. X    case 'w':        /* user interactive mode */
  2057. X        f_disposition = 1;
  2058. X        break;
  2059. X    case 'x':        /* named files are extracted from archive */
  2060. X        f_extract = 1;
  2061. X        break;
  2062. X    case '?':
  2063. X        usage();
  2064. X        exit(EX_ARGSBAD);
  2065. X    }
  2066. X    }
  2067. X
  2068. X    /* check command line argument sanity */
  2069. X    if (f_create + f_extract + f_list + f_append + f_newer != 1) {
  2070. X    (void) fprintf(stderr,
  2071. X       "%s: you must specify exactly one of the c, t, r, u or x options\n",
  2072. X               myname);
  2073. X    usage();
  2074. X    exit(EX_ARGSBAD);
  2075. X    }
  2076. X
  2077. X    /* set the blocking factor, if not set by the user */
  2078. X    if (blocking == 0) {
  2079. X#ifdef USG
  2080. X    if (f_extract || f_list) {
  2081. X        blocking = DEF_BLOCKING;
  2082. X        fprintf(stderr, "Tar: blocksize = %d\n", blocking);
  2083. X    } else {
  2084. X        blocking = 1;
  2085. X    }
  2086. X#else /* !USG */
  2087. X    blocking = 20;
  2088. X#endif /* USG */
  2089. X    }
  2090. X    blocksize = blocking * BLOCKSIZE;
  2091. X    buf_allocate((OFFSET) blocksize);
  2092. X
  2093. X    if (f_create) {
  2094. X    open_archive(AR_WRITE);
  2095. X    create_archive();    /* create the archive */
  2096. X    } else if (f_extract) {
  2097. X    open_archive(AR_READ);
  2098. X    read_archive();        /* extract files from archive */
  2099. X    } else if (f_list) {
  2100. X    open_archive(AR_READ);
  2101. X    read_archive();        /* read and list contents of archive */
  2102. X    } else if (f_append) {
  2103. X    open_archive(AR_APPEND);
  2104. X    append_archive();    /* append files to archive */
  2105. X    }
  2106. X    
  2107. X    if (f_linksleft) {        
  2108. X    linkleft();         /* report any unresolved links */ 
  2109. X    }
  2110. X    
  2111. X    return (0);
  2112. X}
  2113. X
  2114. X
  2115. X/* taropt -  tar specific getopt
  2116. X *
  2117. X * DESCRIPTION
  2118. X *
  2119. X *     Plug-compatible replacement for getopt() for parsing tar-like
  2120. X *     arguments.  If the first argument begins with "-", it uses getopt;
  2121. X *     otherwise, it uses the old rules used by tar, dump, and ps.
  2122. X *
  2123. X * PARAMETERS
  2124. X *
  2125. X *    int argc    - argument count (argc from main) 
  2126. X *    char **argv    - argument list (argv from main) 
  2127. X *    char *optstring    - sring which describes allowable options
  2128. X *
  2129. X * RETURNS
  2130. X *
  2131. X *    Returns the next option character in the option string(s).  If the
  2132. X *    option requires an argument and an argument was given, the argument
  2133. X *    is pointed to by "optarg".  If no option character was found,
  2134. X *    returns an EOF.
  2135. X *
  2136. X */
  2137. X
  2138. X#ifdef __STDC__
  2139. X
  2140. Xstatic int taropt(int argc, char **argv, char *optstring)
  2141. X
  2142. X#else
  2143. X
  2144. Xstatic int taropt(argc, argv, optstring)
  2145. Xint             argc;
  2146. Xchar          **argv;
  2147. Xchar           *optstring;
  2148. X
  2149. X#endif
  2150. X{
  2151. X    extern char    *optarg;    /* Points to next arg */
  2152. X    extern int      optind;    /* Global argv index */
  2153. X    static char    *key;    /* Points to next keyletter */
  2154. X    static char     use_getopt;    /* !=0 if argv[1][0] was '-' */
  2155. X    char            c;
  2156. X    char           *place;
  2157. X
  2158. X    optarg = NULL;
  2159. X
  2160. X    if (key == NULL) {        /* First time */
  2161. X    if (argc < 2)
  2162. X        return EOF;
  2163. X    key = argv[1];
  2164. X    if (*key == '-')
  2165. X        use_getopt++;
  2166. X    else
  2167. X        optind = 2;
  2168. X    }
  2169. X    if (use_getopt) {
  2170. X    return getopt(argc, argv, optstring);
  2171. X    }
  2172. X
  2173. X    c = *key++;
  2174. X    if (c == '\0') {
  2175. X    key--;
  2176. X    return EOF;
  2177. X    }
  2178. X    place = strchr(optstring, c);
  2179. X
  2180. X    if (place == NULL || c == ':') {
  2181. X    fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  2182. X    return ('?');
  2183. X    }
  2184. X    place++;
  2185. X    if (*place == ':') {
  2186. X    if (optind < argc) {
  2187. X        optarg = argv[optind];
  2188. X        optind++;
  2189. X    } else {
  2190. X        fprintf(stderr, "%s: %c argument missing\n",
  2191. X            argv[0], c);
  2192. X        return ('?');
  2193. X    }
  2194. X    }
  2195. X    return (c);
  2196. X}
  2197. X
  2198. X
  2199. X/* usage - print a helpful message and exit
  2200. X *
  2201. X * DESCRIPTION
  2202. X *
  2203. X *    Usage prints out the usage message for the TAR interface and then
  2204. X *    exits with a non-zero termination status.  This is used when a user
  2205. X *    has provided non-existant or incompatible command line arguments.
  2206. X *
  2207. X * RETURNS
  2208. X *
  2209. X *    Returns an exit status of 1 to the parent process.
  2210. X *
  2211. X */
  2212. X
  2213. X#ifdef __STDC__
  2214. X
  2215. Xstatic void usage(void)
  2216. X
  2217. X#else
  2218. X
  2219. Xstatic void usage()
  2220. X
  2221. X#endif
  2222. X{
  2223. X    fprintf(stderr, "\
  2224. XUsage: %s -c[bfvw] device block filename..\n", myname);
  2225. X    fprintf(stderr, "\
  2226. X       %s -r[bvw] device block [filename...]\n", myname);
  2227. X    fprintf(stderr, "\
  2228. X       %s -t[vf] device\n", myname);
  2229. X    fprintf(stderr, "\
  2230. X       %s -u[bvw] device block [filename...]\n", myname);
  2231. X    fprintf(stderr, "\
  2232. X       %s -x[flmovw] device [filename...]\n", myname);
  2233. X    exit(1);
  2234. X}
  2235. END_OF_tar.c
  2236. if test 7881 -ne `wc -c <tar.c`; then
  2237.     echo shar: \"tar.c\" unpacked with wrong size!
  2238. fi
  2239. # end of overwriting check
  2240. fi
  2241. echo shar: End of archive 3 \(of 6\).
  2242. cp /dev/null ark3isdone
  2243. MISSING=""
  2244. for I in 1 2 3 4 5 6 ; do
  2245.     if test ! -f ark${I}isdone ; then
  2246.     MISSING="${MISSING} ${I}"
  2247.     fi
  2248. done
  2249. if test "${MISSING}" = "" ; then
  2250.     echo You have unpacked all 6 archives.
  2251.     rm -f ark[1-9]isdone
  2252. else
  2253.     echo You still need to unpack the following archives:
  2254.     echo "        " ${MISSING}
  2255. fi
  2256. ##  End of shell archive.
  2257. exit 0
  2258.  
  2259.